#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@author: liang kang
@contact: gangkanli1219@gmail.com
@time: 2018/3/17 13:35
@desc: 
"""
import numpy as np

from .basic import is_rectangle_overlap


def get_overlap_area(rect1, rect2):
    """
    计算两个矩形的重叠部分的面积，如果不重叠返回0

    Parameters
    ----------
    rect1: 矩形1，形如[axis1_min, axis2_min, axis1_max, axis2_max]
    rect2: 矩形2，形如[axis1_min, axis2_min, axis1_max, axis2_max]

    Returns
    -------

    """
    if not is_rectangle_overlap(rect1, rect2):
        return 0.0
    xmin = max(rect1[0], rect2[0])
    ymin = max(rect1[1], rect2[1])
    xmax = min(rect1[2], rect2[2])
    ymax = min(rect1[3], rect2[3])
    return (xmax - xmin) * (ymax - ymin)


def get_point_from_box(boxes, weights=(0.5, 0.5)):
    """
    从一系列类似矩形的`box`中获取点

    Parameters
    ----------
    boxes: 一系列类似[axis1_min, axis2_min, axis1_max, axis2_max]的`box`
    weights: axis1_min 和 axis2_min的权值

    Returns
    -------

    """
    points = []
    for box in boxes:
        points.append(
            [weights[0] * box[0] + (1 - weights[0]) * box[2],
             weights[1] * box[1] + (1 - weights[1]) * box[3]])
    return points


def get_revolve_info(angle, shape, reverse=False):
    """
    获取旋转矩阵，旋转前或旋转后的图像形状，中心偏移量

    Parameters
    ----------
    angle: 旋转角度
    shape: 旋转前或旋转后的图像形状, 当 `reverse` 为 `False`，为旋转前
    reverse: `True` 表明将旋转后的的对象还原，`False` 表明旋转对象

    Returns
    -------
    旋转矩阵， 旋转前或旋转后的图像形状， 中心偏移量
    """
    arc = angle * np.pi / 180
    _shape = (
        np.ceil(abs(shape[0] * np.cos(arc)) +
                abs(shape[1] * np.sin(arc))).astype(np.int32),
        np.ceil(abs(shape[0] * np.sin(arc)) +
                abs(shape[1] * np.cos(arc))).astype(np.int32))
    offset = list(map(lambda x, y: (x - y) // 2, _shape, shape))
    if reverse:
        arc = -arc
        other_shape, shape = shape, _shape
    else:
        other_shape = _shape
    revolve_mat_1 = np.matrix([[1, 0, 0],
                               [0, -1, 0],
                               [-0.5 * shape[1], 0.5 * shape[0], 1]])
    revolve_mat_2 = np.matrix([[np.cos(arc), -np.sin(arc), 0],
                               [np.sin(arc), np.cos(arc), 0],
                               [0, 0, 1]])
    revolve_mat_3 = np.matrix([[1, 0, 0],
                               [0, -1, 0],
                               [0.5 * other_shape[1], 0.5 * other_shape[0], 1]])
    return revolve_mat_1 * revolve_mat_2 * revolve_mat_3, _shape, offset


def revolve_boxes(boxes, revolve_mat, src_shape, dst_shape=None):
    """
    将 box 旋转到目标角度

    Parameters
    ----------
    boxes
    revolve_mat
    src_shape
    dst_shape

    Returns
    -------

    """
    if dst_shape is None:
        dst_shape = src_shape
    result_boxes = []
    for box in boxes:
        points = np.matrix([[box[1] * src_shape[1], box[0] * src_shape[0], 1],
                            [box[3] * src_shape[1], box[0] * src_shape[0], 1],
                            [box[1] * src_shape[1], box[2] * src_shape[0], 1],
                            [box[3] * src_shape[1], box[2] * src_shape[0], 1]])
        revolved_points = points * revolve_mat
        min_x, min_y, max_x, max_y = dst_shape[1], dst_shape[0], 0, 0
        for point in revolved_points.tolist():
            min_x = min(min_x, point[0])
            min_y = min(min_y, point[1])
            max_x = max(max_x, point[0])
            max_y = max(max_y, point[1])
        result_boxes.append([min_y / dst_shape[0], min_x / dst_shape[1],
                             max_y / dst_shape[0], max_x / dst_shape[1]])
    return result_boxes
